#include "server.h"

#include <iostream>

using namespace std;

Server::Server(asio::io_service& service_, const server_options& opt_)
: opt(opt_)
, service(service_)
, udpsock(service_)
, udpservice(service_, udpsock)
{
	udpsock.open(opt.udp_listen_addr.protocol());
	udpsock.bind(opt.udp_listen_addr);

	handle_udp_receive(boost::system::error_code(), 0);
	handle_udp_accept(boost::system::error_code(), ServerConnRef());
}

void Server::handle_udp_receive(const boost::system::error_code& e, std::size_t len)
{
#ifdef SIMULATE_PACKETLOSS
	if ((rand()&0xff) < 0x0f) {
		cerr << "Dropping packet..." << endl;
	} else
#endif
	if (!e && len >= 4) {
		uint32 header = (udppackbuf[0] << 24) | (udppackbuf[1] << 16) | (udppackbuf[2] <<  8) | (udppackbuf[3] <<  0);
		if ((header & 0xff) == 0x02)
			udpservice.handle_read(udppackbuf, len, &udppeer);
		//else if (header == 0xff133703)
		//  do something?
		else
			cerr << "Invalid udp packet received." << endl;
	}
	if (e) {
		cerr << "Error receiving udp packet: " << e.message() << endl;
	}
	udpsock.async_receive_from(boost::asio::buffer(udppackbuf, udppackbufsize), udppeer,
		boost::bind(&Server::handle_udp_receive, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)
	);
}

void Server::handle_udp_accept(const boost::system::error_code& e, ServerConnRef conn)
{
	if (!e && conn) {
		conn->giveSelfRef(conn);
		conn->handleUdpAccept();
	}
	if (e) {
		cerr << "Error handling udp accept: " << e.message() << endl;
		//Sleep(1000);
	}

	conn = ServerConnRef(new ServerConn(service, udpservice, opt));
	conn->getUdpConn().async_accept(
		boost::bind(&Server::handle_udp_accept, this, boost::asio::placeholders::error, conn)
	);
}
